package io.github.fb513.transport.handler;

import com.fasterxml.jackson.databind.JsonNode;
import io.github.fb513.common.enums.CommandEnum;
import io.github.fb513.transport.command.CommandChain;
import io.github.fb513.common.model.MessageInfo;
import io.github.fb513.transport.model.UserInfo;
import io.github.fb513.transport.model.UserSession;
import io.github.fb513.transport.util.JsonUtils;
import io.github.fb513.transport.util.SessionHolder;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ServerHandler extends SimpleChannelInboundHandler<MessageInfo<JsonNode>> {

    private final CommandChain commandChain;

    public ServerHandler(CommandChain commandChain) {
        this.commandChain = commandChain;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, MessageInfo<JsonNode> msg) {
        commandChain.execute(ctx, msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("Exception caught", cause);
        super.exceptionCaught(ctx, cause);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("---inactive---");
        UserSession session = SessionHolder.getSession(ctx);
        if (session != null) {
            log.info("channelInactive:{}", session.getUserInfo().getUserId());
            session.close();
            MessageInfo<UserInfo> message = MessageInfo.getJsonMessage(CommandEnum.OFFLINE.getCommand(), session.getUserInfo());
            commandChain.sendToMQAsync(JsonUtils.formatObjToJson(message));
        }
        super.channelInactive(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent event && event.state() == IdleState.ALL_IDLE) {
            log.info("--------------------channelIdle--------------------");
            UserSession session = SessionHolder.getSession(ctx);
            if (session != null) {
                session.sendMsg(MessageInfo.getJsonMessage(CommandEnum.HEARTBEAT.getCommand()));
            } else {
                ctx.close();
            }
        }
        super.userEventTriggered(ctx, evt);
    }
}
